;/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;*  Copyleft (!c) 2004-2005 Div. Nucl. Med., Cyric, Tohoku Univ.    *
;*  Copyleft (!c) 2005-2011 Elseif Laboratory.                      *
;*  elseifkk@users.sf.net                                           *
;*                                                                  *
;*  All Rights Reversed.                                            *
;*                                                                  *
;*                                                                  *
;*  LICENSE AGREEMENT:                                              *
;*                                                                  *
;*  You agree that we don't agree to anything.                      *
;*                                                                  *
;*                                                                  *
;*  DISCLAIMER OF WARRANTIES:                                       *
;*                                                                  *
;*  This software is provided to you "AS IS," and the authors and   *
;*  contributors disclaim any warranty or liability obligations to  *
;*  you of any kind, implied or express, including but not limited  *
;*  to the warranties of merchantability, fitness for a particular  *
;*  purpose, and non-infringement.                                  *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
section .data
open_flag	dd 0
open_mode	dd 0
function_magic	dd 0
str_buf  	dd 0
NL		dd 10
ERRSYS_NTSTR	equ -1024
ERRSYS_OPEN	equ -5
ERRSYS_READ	equ -3
ERRSYS_WRITE    equ -4
;;; 
section .text
global sizeoffile_
global fopenread_
global fopenwrite_
global mess_
global messn_
global fexist_
;;; 
_syscall:
%ifdef _LINUX_
	mov edx, [esp+12]
	mov ecx, [esp+8]	
	mov ebx, [esp+4]
%endif	
	int 0x80
	ret
;;; integer*4 funtion sizeoffile_asm(file)
;;; character*(*),intent(in)::file
%macro len_trim 2		; str, len
;;; input:	
;;;   edi = str
;;;   ecx = len
;;; output:
;;;   edi = rightmost nonwhite char
;;;   ecx = length of str
;;; destroy = eax
	or %2, %2
  	jz .exit_len_trim
	add %1, %2
.do_len_trim:
	dec %1
	mov al, byte [%1]
	cmp al, 32
  	ja .exit_len_trim
	dec %2
  	jnz .do_len_trim
.exit_len_trim:
%endmacro
;;;
%macro open 3			; path, flag, mode
	push %3			; mode
 	push %2			; flag
	push %1			; *path
	mov eax, 5		; open
	call _syscall
	add esp, 12		; clean stack
%endmacro
;;; 
%macro close 1
	push %1			; fd
	mov eax, 6		; close
	call _syscall
	add esp, 4		; clean stack
%endmacro	
;;; 
%macro fopen 4			; ptr path, ptr len, flag, mode 
 	mov ecx, [%2]
 	mov esi, [%1]
 	open esi, %3, %4	; 
 	cmp eax, 2		; eax=fd
    	jle near .failure_open	; 	
%endmacro	
;;; 
sizeoffile_:	
	push edi
	push esi
	push ebx
%assign _P 4*3
	mov ebx, [esp+_P+4]	; ebx = file
	mov ecx, [esp+_P+8]	; ecx = len(file)
	mov edi, ebx
 	fopen esp+_P+4, esp+_P+8, dword 0, dword 0
	push eax		; push fd for close
.call_lseek:
	push 2			; SEEK_END
	push 0			; offset
	push eax		; fd
	mov eax, 19		; lseek
	call _syscall
	add esp, 12		; clean stack
.ret_lseek:
	pop edx			; restore fd
	push eax 		; save filesize
.call_close:
	close edx
.ret_close:
	pop eax			; restore filesize
.exit:	
	pop ebx
	pop esi
	pop edi
	ret
	;; 
.failure_nt:			; cannot nullterminate
	mov eax, ERRSYS_NTSTR
	jmp .exit
.failure_open:
	mov eax, ERRSYS_OPEN
	jmp .exit
	;;
;;;
;;; fopenread(fin,buf,nbyte,nseek,(len_fin))
_fopenreadwrite:
	push edi
	push esi
	push ebx
	;;
%assign _P 4*3
  	fopen esp+_P+4, esp+_P+20, dword [open_flag], dword [open_mode]
	push eax		; save fd for close
	;; 
	mov edx, eax		; edx = fd
 	mov eax, [esp+_P+16+4]	; ptr nseek
 	mov eax, [eax]
 	or eax, eax
 	jz .seek_done
 	push edx		; save fd
 	push 0			; SEEK_SET
 	push eax		; offset
 	push edx		; fd
 	mov eax, 19		; lseek
 	call _syscall
 	add esp, 12		; clean stack
 	pop edx
.seek_done:
	mov eax, [esp+_P+12+4]	; eax=ptr nbyte
	mov eax, [eax]		; eax=nbyte
.call_read:	
	push eax		; nbyte
	mov eax, [esp+_P+8+4*2]	; eax=ptr buf
	push eax		; 
	push edx		; edx=fd
	mov eax, [function_magic]
	call _syscall		;
	add esp, 12
.ret_read:	
	mov ebx, [esp+_P+12+4]	; ptr nbyte
	cmp eax, [ebx]		;
	jne near .failure_read	; 
	xor eax, eax		; return code
.close_file:
	pop edx			; restore fd
	push eax		; save return code
	push edx		; close edx=fd
	mov eax, 6
	call _syscall
	add esp, 4
	pop eax			; return code
.exit:	
	pop ebx
	pop esi
	pop edi
	ret	
.failure_open:
	mov eax, ERRSYS_OPEN
	jmp .exit
.failure_nt:		
	mov eax, ERRSYS_NTSTR
	jmp .exit
.failure_read:
	mov eax, [function_magic]
	neg eax
	jmp .close_file
;;; 
fopenread_:
	mov dword [function_magic], 3
	mov dword [open_flag], 0
	mov dword [open_mode], 0x1FF ; = 777o
	jmp _fopenreadwrite
fopenwrite_:
	mov dword [function_magic], 4
%ifdef LINUX
	mov dword [open_flag], 0x0241 ; = CREATE OR TRUNC OR WRITE
%else
	mov dword [open_flag], 0x0601 ; = CREATE OR TRUNC OR WRITE
%endif
	mov dword [open_mode], 0x1A0 ; = 640o
	jmp _fopenreadwrite
;;;
;;;
;;; subroutine mess(str)
messn_:
	mov dword [function_magic], 1
	jmp _mess	
mess_:	
	mov dword [function_magic], 0
_mess:
	push edi
	push esi
	push ebx
%assign _P 4*3
	mov ecx, [esp+_P+8]
	mov edx, [esp+_P+4]
	push ecx
	push edx
	push dword 1
	mov eax, 4
	call _syscall
	add esp, 12
	cmp [function_magic], byte 0
	je .exit
	mov ecx, 1
	mov edx, NL
	push ecx
	push edx
	push dword 1
	mov eax, 4
	call _syscall
	add esp, 12
.exit:
	pop ebx
	pop esi
	pop edi
	ret
;;;
;;; exist(file)
fexist_:
	push edi
	push esi
	push ebx
%assign _P 4*3
 	mov ecx, [esp+_P+8]
 	mov esi, [esp+_P+4]
  	len_trim esi, ecx	; path, len
 	cmp ecx, [esp+_P+8]	; trimed len ecx must < len(file) 
    	je near .failure_nt
 	mov byte [esi+1], 0	; null terminate
 	push esi		; save null terminated pos
 	sub esi, ecx
 	inc esi
	push dword 0		; F_OK
	push esi		; ptr path
	mov eax, 33		; access
	call _syscall
	add esp, 8
 	pop esi			; restore null terminated pos
 	mov byte [esi+1], 0x20	; erase terminating null
.exit:
	pop ebx
	pop esi
	pop edi
	ret
.failure_nt:		
	mov eax, ERRSYS_NTSTR
	jmp .exit
